﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using Kotonoha.Server.Dictionaries;
using log4net;

namespace Kotonoha.Server.Plugins {
    public class PluginManager {
        private static readonly PluginManager instance = new PluginManager();
        private readonly ILog log = LogManager.GetLogger(typeof (PluginManager));

        private PluginManager() {}

        public static PluginManager Instance {
            [DebuggerStepThrough]
            get { return instance; }
        }

        private readonly AttributedClassLoader loader = new AttributedClassLoader(typeof(PluggableReaderAttribute));
        private readonly List<CharPlugin> charPlugins = new List<CharPlugin>();
        private readonly List<WordPlugin> wordPlugins = new List<WordPlugin>();

        public List<CharPlugin> CharPlugins {
            [DebuggerStepThrough]
            get { return charPlugins; }
        }

        public List<WordPlugin> WordPlugins {
            [DebuggerStepThrough]
            get { return wordPlugins; }
        }


        public WordPlugin FindWordPlugin(string name) {
            return (from plugin in wordPlugins where plugin.Name.Equals(name) select plugin).First();
        }

        public CharPlugin FindCharPlugin(string name) {
            return (from plugin in charPlugins where plugin.Name.Equals(name) select plugin).First();
        }

        public int Load(DirectoryInfo dir) {
            int loaded = 0;
            log.DebugFormat("Loading plugins from {0}", dir.FullName);
            foreach(FileInfo file in dir.GetFiles("*.dll")) {
                int cnt = Load(file);
                loaded += cnt;
            }
            log.DebugFormat("Totally loaded {0} plugins", loaded);
            return loaded;
        }

        public int Load(FileInfo file) {
            int loaded = 0;
            try {
                foreach(Type t in loader.load(file.FullName)) {
                    if (typeof(IWordDictionaryReader).IsAssignableFrom(t)) {
                        WordPlugin plugin = WordPlugin.Create(t);
                        wordPlugins.Add(plugin);
                        log.DebugFormat("Loaded {0} from {1}", plugin.Name, file.Name);
                        ++loaded;
                    } else if (typeof(ICharDictionaryReader).IsAssignableFrom(t)) {
                        CharPlugin plugin = CharPlugin.Create(t);
                        charPlugins.Add(plugin);
                        log.DebugFormat("Loaded {0} from {1}", plugin.Name, file.Name);
                        ++loaded;
                    }
                }
            } catch (Exception e) {
                log.Error("Failed to load " + file.Name, e);
            }
            return loaded;
        }
    }
}
